/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package aliasMatching.cluster.fusion;

import aliasMatching.controller.TestFile;
import aliasMatching.controller.TimeClustering;
import aliasMatching.model.Alias;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * clustering the user according to their passive time. the users are divided
 * into86 different cluster wrt time where they don't post anything in the
 * forum. After that the users clusters are created when they are mostly active
 * in discussion board.
 *
 * @author amendrashrestha
 */
public class SixUserClusterFusion {

    static List users = new ArrayList();
    static List postTime = new ArrayList();
    static List cluster0004 = new ArrayList();
    static List cluster0408 = new ArrayList();
    static List cluster0812 = new ArrayList();
    static List cluster1216 = new ArrayList();
    static List cluster1620 = new ArrayList();
    static List cluster2000 = new ArrayList();
    static List nullcluster = new ArrayList();
    static List users0004 = new ArrayList();
    static List users0408 = new ArrayList();
    static List users0812 = new ArrayList();
    static List users1216 = new ArrayList();
    static List users1620 = new ArrayList();
    static List users2000 = new ArrayList();
    static List firstActivityPeak0004 = new ArrayList();
    static List firstActivityPeak0408 = new ArrayList();
    static List firstActivityPeak0812 = new ArrayList();
    static List firstActivityPeak1216 = new ArrayList();
    static List firstActivityPeak1620 = new ArrayList();
    static List firstActivityPeak2000 = new ArrayList();
    static HashMap<String, double[]> map = new HashMap<String, double[]>();
    static HashMap<List, List> activityPeakMap = new HashMap<List, List>();
    static HashMap<String, List> matchedUserMap;
    static HashMap<String, List> matrixMap = new HashMap<String, List>();
    static List firstUserPostTime, secondUserPostTime;
    static double[] timeStamp;
    static String firstUser, secondUser;
    private static List userPostsTime;
    private static List<Alias> styloUser = new ArrayList();
    static HashMap<String, List> totalSleepingMap;
    static HashMap<String, List> totalActivityMap;
    static ArrayList<String> matchedUser;
    static int success = 0;
    static int failure = 0;
    static int sleepingSuccess = 0;
    static int sleepingFailure = 0;
    static int activeSuccess = 0;
    static int activeFailure = 0;
    private static ArrayList totalUserCluster;
    private static ArrayList totalSleepingUserCluster;

    public SixUserClusterFusion() {
    }

    public static void main(String args[]) {
        Alias tf = new Alias();
        TimeStyloClusterEqualityTest init = new TimeStyloClusterEqualityTest();

        try {
            users = tf.getAllUsers();

            splitUser(users);

            totalUserCluster = new ArrayList();
            totalUserCluster.add(cluster0004);
            totalUserCluster.add(cluster0408);
            totalUserCluster.add(cluster0812);
            totalUserCluster.add(cluster1216);
            totalUserCluster.add(cluster1620);
            totalUserCluster.add(cluster2000);

            totalSleepingUserCluster = new ArrayList();
            totalSleepingUserCluster.add(users0004);
            totalSleepingUserCluster.add(users0408);
            totalSleepingUserCluster.add(users0812);
            totalSleepingUserCluster.add(users1216);
            totalSleepingUserCluster.add(users1620);
            totalSleepingUserCluster.add(users2000);
            totalSleepingUserCluster.add(nullcluster);

            calculateMatchedList(totalUserCluster);

            System.out.println("\nMatched Cluster");

            for (Map.Entry<String, List> peakMapEntry : matchedUserMap.entrySet()) {
                System.out.println(peakMapEntry);
            }

            /**
             * Finding the matched user percentage
             */
            HashSet hs = new HashSet();
            for (Map.Entry<String, List> MatrixEntry : matchedUserMap.entrySet()) {
                List values = MatrixEntry.getValue();
                splitactiveUser(values);
                calculateMatchedList(totalSleepingUserCluster);
                
                System.out.println("\nMatched Users: ");
                System.out.println(matchedUserMap);
                init.calculateTimeStyloEquality(matchedUserMap);

                clearList();
                hs.addAll(values);
                values.clear();
                values.addAll(hs);
                System.out.println("User Size: " + values.size());
            }

            int userSize = users.size();
            double matchedUsersSize = (double) hs.size();
            System.out.println("\nActivity Matched User Size with duplicates: " + matchedUsersSize);
            System.out.println("\nActivity Most Matched Percentage with duplicates: " + (matchedUsersSize * 100) / userSize);
        } catch (SQLException ex) {
        }
    }

    public static void splitactiveUser(List user) {
        try {
            TimeClustering se = new TimeClustering(user);
            styloUser = se.aliases;
            int userSize = styloUser.size();

            Alias[] tempAlias = new Alias[userSize + 1];
            String[] tempUser = new String[userSize + 1];

            for (int i = 0; i < user.size(); i++) {
                tempUser[i] = styloUser.get(i).getUser();
                divideTime(tempUser[i]);
                styloUser.remove(i);

                tempAlias[i] = new Alias(firstUser);
                tempAlias[i].setPostTime(firstUserPostTime);

                double[] tempTimeVectorA = Alias.getTimeVectorArray(firstUserPostTime);
                //dividing posts into clusters
                inactivityCluster(tempTimeVectorA, firstUser);
                styloUser.add(0, tempAlias[i]);

                //for second user
                tempAlias[i + 1] = new Alias(secondUser);
                tempAlias[i + 1].setPostTime(secondUserPostTime);

                double[] tempTimeVectorB = Alias.getTimeVectorArray(secondUserPostTime);

                inactivityCluster(tempTimeVectorB, secondUser);
                styloUser.add(tempAlias[i + 1]);
            }

        } catch (SQLException ex) {
            Logger.getLogger(SixUserClusterFusion.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * calculates the number of users where UserX_A and UserX_B go to the same
     * cluster
     *
     * @param ActivityPeakUsers
     * @param clusterSize
     */
    private static HashMap calculateMatchedList(List<List> ActivityPeakUsers) {
        matchedUserMap = new HashMap<String, List>();

        for (int a = 0; a < ActivityPeakUsers.size(); a++) {
            List userA = new ArrayList();
            List userB = new ArrayList();
            List bUsers = ActivityPeakUsers.get(a);

            matchedUser = new ArrayList<String>();
            for (int b = 0; b < bUsers.size(); b++) {
                String tempUsers = bUsers.get(b).toString();

                if (tempUsers.contains("_")) {
                    String realUser = returnUser(tempUsers);
                    if (tempUsers.contains("_A")) {
                        userA.add(realUser);
                    } else {
                        userB.add(realUser);
                    }
                }

            } // end for
            if (userA.size() > 0 && userB.size() > 0) {
                List tempList = new ArrayList();
                // tempList.add(userA.get(0).toString());

                for (int i = 0; i < userA.size(); i++) {
                    for (int j = 0; j < userB.size(); j++) {
                        if (userA.get(i).equals(userB.get(j))) {
                            tempList.add(userA.get(i));
                            matchedUserMap.put(String.valueOf(a + 1), tempList);
                            break;
                        }
                    }
                }
                userA.clear();
                userB.clear();
            }
        }
        return matchedUserMap;
    }

    /**
     * return userID by removing _A or _B
     *
     * @param userID
     * @return
     */
    public static String returnUser(String userID) {
        String num = "";
        String regex = "(\\d+)";
        Matcher matcher = Pattern.compile(regex).matcher(userID);
        while (matcher.find()) {
            num = matcher.group();
            //System.out.println(num);
        }
        return num;
    }

    /**
     * the UserX is divided into UserX_A and UserX_B and respectively the post
     * time of UserX is also divided between UserX_A and UserX_B.
     *
     * @param user
     * @throws SQLException
     */
    public static void splitUser(List user) throws SQLException {

        TimeClustering se = new TimeClustering(user);
        styloUser = se.aliases;
        int userSize = styloUser.size();

        Alias[] tempAlias = new Alias[userSize + 1];
        String[] tempUser = new String[userSize + 1];

        for (int i = 0; i < userSize; i++) {

            tempUser[i] = styloUser.get(i).getUser();
            divideTime(tempUser[i]);
            styloUser.remove(i);

            tempAlias[i] = new Alias(firstUser);
            tempAlias[i].setPostTime(firstUserPostTime);

            double[] tempTimeVectorA = Alias.getTimeVectorArray(firstUserPostTime);

            //dividing posts into clusters
            createCluster(tempTimeVectorA, firstUser);

            styloUser.add(0, tempAlias[i]);
            //for second user
            tempAlias[i + 1] = new Alias(secondUser);
            tempAlias[i + 1].setPostTime(secondUserPostTime);

            double[] tempTimeVectorB = Alias.getTimeVectorArray(secondUserPostTime);

            createCluster(tempTimeVectorB, secondUser);
            styloUser.add(tempAlias[i + 1]);
        }
    }

    private static void createCluster(double[] TimeVector, String User) {
        double[] post_count = TimeVector;
        double totalPost = 0.0;

        for (double i : post_count) {
            totalPost += i;
        }

        double threshHold = (20 * totalPost) / 100;
        double firstClusterSize = post_count[0] + post_count[1] + post_count[2] + post_count[3];
        double secondClusterSize = post_count[4] + post_count[5] + post_count[6] + post_count[7];
        double thirdClusterSize = post_count[8] + post_count[9] + post_count[10] + post_count[11];
        double fourthClusterSize = post_count[12] + post_count[13] + post_count[14] + post_count[15];
        double fifthClusterSize = post_count[16] + post_count[17] + post_count[18] + post_count[19];
        double sixthClusterSize = post_count[20] + post_count[21] + post_count[22] + post_count[23];

        if (firstClusterSize > threshHold) {
            cluster0004.add(User);
        }
        if (secondClusterSize > threshHold) {
            cluster0408.add(User);
        }
        if (thirdClusterSize > threshHold) {
            cluster0812.add(User);
        }
        if (fourthClusterSize > threshHold) {
            cluster1216.add(User);
        }
        if (fifthClusterSize > threshHold) {
            cluster1620.add(User);
        }
        if (sixthClusterSize > threshHold) {
            cluster2000.add(User);
        }
    }

    public static void clearList() {
//        if (!totalUserList.isEmpty()) {
//            totalUserList.clear();
//        }
        if (!nullcluster.isEmpty()) {
            nullcluster.clear();
        }
        if (!users0004.isEmpty()) {
            users0004.clear();
        }
        if (!users0408.isEmpty()) {
            users0408.clear();
        }
        if (!users0812.isEmpty()) {
            users0812.clear();
        }
        if (!users1216.isEmpty()) {
            users1216.clear();
        }
        if (!users1620.isEmpty()) {
            users1620.clear();
        }
        if (!users2000.isEmpty()) {
            users2000.clear();
        }
    }

    /**
     * creating clusters of users having same activity peak time cluster
     *
     * @param user
     * @param activityPeak
     */
    public static void activityPeakCluster(List activityPeak, String activityUser1) {
        List userList = new ArrayList();
        //System.out.println("activityUser: " + activityUser1);
        userList.add(activityUser1);
        if (activityPeakMap.containsKey(activityPeak)) {
            List temp = activityPeakMap.get(activityPeak);
            temp.add(activityUser1);

            activityPeakMap.put(activityPeak, temp);
        } else {
            activityPeakMap.put(activityPeak, userList);
        }
    }

    /**
     * return normalized time vector with respect to total number of post
     *
     * @param timeVector
     * @return
     */
    public static double[] returnNormalizedTimeVector(double[] timeVector) {
        double sumB = 0;

        for (int index = 0; index < timeVector.length; index++) {
            sumB = sumB + timeVector[index];
        }

        for (int index = 0; index < timeVector.length; index++) {
            timeVector[index] = timeVector[index] / sumB;
        }
        return timeVector;
    }

    /**
     * returns index of maximum number of posts done
     *
     * @param hour
     * @return
     */
    public static int peakHourIndex(double[] hour) {
        int maxHourIndex = 0;
        double maxHour = 0.0;
        for (int i = 0; i < hour.length; i++) {
            if (hour[i] > maxHour) {
                maxHour = hour[i];
                maxHourIndex = i;
            }
        }
        return maxHourIndex;
    }

    /**
     * creating cluster according to their inactivity in discussion board
     *
     * @param time
     * @param user
     */
    public static void inactivityCluster(double[] time, String user) {

        double[] post_count = time;
        boolean contains = false;

        if (post_count[0] + post_count[1] + post_count[2] + post_count[3] == 0) {
            users0004.add(user);
            contains = true;
        }
        if (post_count[4] + post_count[5] + post_count[6] + post_count[7] == 0) {
            users0408.add(user);
            contains = true;
        }
        if (post_count[8] + post_count[9] + post_count[10] + post_count[11] == 0) {
            users0812.add(user);
            contains = true;
        }
        if (post_count[12] + post_count[13] + post_count[14] + post_count[15] == 0) {
            users1216.add(user);
            contains = true;
        }
        if (post_count[16] + post_count[17] + post_count[18] + post_count[19] == 0) {
            users1620.add(user);
            contains = true;
        }
        if (post_count[20] + post_count[21] + post_count[22] + post_count[23] == 0) {
            users2000.add(user);
            contains = true;
        }
        if (contains == false) {
            nullcluster.add(user);
        }
    }

    /**
     * dividing single user into two user
     *
     * @param ID
     * @throws SQLException
     */
    public static void divideTime(String ID) throws SQLException {
        dividePostTime(ID);
        firstUser = ID + "_A";
        secondUser = ID + "_B";
    }

    /**
     * Splitting posts between users where message posted on odd day of month
     * goes to UserA and even days message to UserB
     *
     * @param args
     * @throws SQLException
     */
    public static void dividePostTime(String ID) throws SQLException {
        userPostsTime = Alias.getAllPostTime(Integer.parseInt(ID));
        firstUserPostTime = new ArrayList();
        secondUserPostTime = new ArrayList();


        for (int i = 0; i < userPostsTime.size(); i++) {
//            String date = userPostsTime.get(i).toString();
//            int day = Integer.parseInt(date.substring(8, 10));
            /**
             * The odd days post are assigned to first split user and even days
             * posts are assigned to second split user.
             */
            // System.out.println(day % 2);
            if (i % 2 != 0) {
                firstUserPostTime.add(userPostsTime.get(i));
            } else {
                secondUserPostTime.add(userPostsTime.get(i));
            }

        }
    }
}
